package com.simple.gateway.center.domian.manage.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.simple.gateway.center.basedata.common.PageUtil;
import com.simple.gateway.center.basedata.common.SimpleGatewayConstants;
import com.simple.gateway.center.domian.manage.bo.ApplicationSystemRichBO;
import com.simple.gateway.center.domian.manage.bo.GatewayDistributionBO;
import com.simple.gateway.center.domian.manage.bo.GatewayServerBO;
import com.simple.gateway.center.domian.manage.bo.GatewayServerDetailBO;
import com.simple.gateway.center.domian.manage.dto.GatewayDistributionDTO;
import com.simple.gateway.center.domian.manage.dto.GatewayServerDTO;
import com.simple.gateway.center.domian.manage.dto.GatewayServerDetailDTO;
import com.simple.gateway.center.domian.manage.param.RegisterGatewayServerParam;
import com.simple.gateway.center.domian.manage.repository.IConfigManageRepository;
import com.simple.gateway.center.application.IConfigManageService;
import com.simple.gateway.center.domian.application.bo.ApplicationInterfaceBO;
import com.simple.gateway.center.domian.application.bo.ApplicationInterfaceMethodBO;
import com.simple.gateway.center.domian.application.bo.ApplicationSystemBO;
import com.simple.gateway.center.domian.application.repository.IApplicationManageRepository;
import com.simple.gateway.center.web.param.GatewayServerCompositeParam;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 项目: simple-gateway-core
 * <p>
 * 功能描述:
 *
 * @author: WuChengXing
 * @create: 2023-08-07 11:31
 **/
@Service
public class ConfigManageServiceImpl implements IConfigManageService {

    @Resource
    private IConfigManageRepository configManageRepository;

    @Resource
    private IApplicationManageRepository registerManageRepository;

    @Override
    public List<GatewayServerDTO> queryGatewayServerList() {
        List<GatewayServerBO> gatewayServerBOS = configManageRepository.queryGatewayServerList();
        return gatewayServerBOS.stream().map(GatewayServerBO::bo2Dto).collect(Collectors.toList());
    }

    @Override
    public boolean registerGatewayServerNode(RegisterGatewayServerParam param) {
        GatewayServerDetailBO gatewayServerDetailBO = configManageRepository.queryGatewayServerDetail(param.getGatewayId(), param.getGatewayAddress());
        if (null == gatewayServerDetailBO) {
            try {
                return configManageRepository.registerGatewayServerNode(param.getGroupId(), param.getGatewayId(), param.getGatewayName(), param.getGatewayAddress(), SimpleGatewayConstants.GatewayStatus.AVAILABLE);
            } catch (DuplicateKeyException e) {
                return configManageRepository.updateGatewayStatus(param.getGatewayId(), param.getGatewayAddress(), SimpleGatewayConstants.GatewayStatus.AVAILABLE);
            }
        } else {
            return configManageRepository.updateGatewayStatus(param.getGatewayId(), param.getGatewayAddress(), SimpleGatewayConstants.GatewayStatus.AVAILABLE);
        }
    }

    @Override
    public ApplicationSystemRichBO queryApplicationSystemRichInfo(String gatewayId, String systemId) {
        // 1. 查询出网关ID对应的关联系统ID集合。也就是一个网关ID会被分配一些系统RPC服务注册进来，需要把这些服务查询出来。
        List<String> systemIdList = new ArrayList<>();
        if (StrUtil.isEmpty(systemId)) {
            systemIdList = configManageRepository.queryGatewayDistributionSystemIdList(gatewayId);
        } else {
            systemIdList.add(systemId);
        }
        // 2. 查询系统ID对应的系统列表信息
        List<ApplicationSystemBO> applicationSystemVOList = registerManageRepository.queryApplicationSystemList(systemIdList);
        // 3. 查询系统下的接口信息
        // 思考：这里的查询是一个不断地循环的查询，你是否有办法优化下，减少查询次数。
        for (ApplicationSystemBO applicationSystemBO : applicationSystemVOList) {
            List<ApplicationInterfaceBO> applicationInterfaceBOList = registerManageRepository.queryApplicationInterfaceList(applicationSystemBO.getSystemId());
            for (ApplicationInterfaceBO applicationInterfaceBO : applicationInterfaceBOList) {
                List<ApplicationInterfaceMethodBO> applicationInterfaceMethodBOList = registerManageRepository.queryApplicationInterfaceMethodList(applicationSystemBO.getSystemId(), applicationInterfaceBO.getInterfaceId());
                applicationInterfaceBO.setApplicationInterfaceMethodBOS(applicationInterfaceMethodBOList);
            }
            applicationSystemBO.setApplicationInterfaceBOS(applicationInterfaceBOList);
        }
        return new ApplicationSystemRichBO(gatewayId, applicationSystemVOList);
    }

    @Override
    public String queryGatewayDistribution(String systemId) {
        return configManageRepository.queryGatewayDistribution(systemId);
    }

    @Override
    public Page<GatewayServerDTO> pageGatewayServer(String groupName, Integer pageNum, Integer pageSize) {
        Page<GatewayServerBO> gatewayServerBOPage = configManageRepository.pageGatewayServer(groupName, pageNum, pageSize);
        List<GatewayServerDTO> collect = gatewayServerBOPage.getRecords().stream().map(GatewayServerBO::bo2Dto).collect(Collectors.toList());
        return PageUtil.convertPage(gatewayServerBOPage, collect);
    }

    @Override
    public Page<GatewayServerDetailDTO> pageGatewayServerDetail(GatewayServerCompositeParam param) {
        Page<GatewayServerDetailBO> gatewayServerDetailBOPage = configManageRepository.pageGatewayServerDetail(param);
        List<GatewayServerDetailDTO> collect = gatewayServerDetailBOPage.getRecords().stream().map(GatewayServerDetailBO::bo2Dto).collect(Collectors.toList());
        return PageUtil.convertPage(gatewayServerDetailBOPage, collect);
    }

    @Override
    public Page<GatewayDistributionDTO> pageGatewayDistribution(GatewayServerCompositeParam param) {
        Page<GatewayDistributionBO> gatewayDistribution = configManageRepository.pageGatewayDistribution(param);
        List<GatewayDistributionDTO> collect = gatewayDistribution.getRecords().stream().map(GatewayDistributionBO::bo2Dto).collect(Collectors.toList());
        return PageUtil.convertPage(gatewayDistribution, collect);
    }
}
